package de.tum.wi.som.rcpsp.business.impl;

import de.tum.wi.som.rcpsp.entities.Activity;
import de.tum.wi.som.rcpsp.entities.WorkContentResource;
import de.tum.wi.som.rcpsp.util.ArraysUtil;

public class ConsistencyCheck {

	private int remainingResources;

	private int actualMaxValue;

	private int lowerBound;

	private Integer[] resource;
	private Integer[] blockLength;

	private WorkContentResource wcr;

	public ConsistencyCheck(WorkContentResource workContentResource,
			Activity activity, int minBlockLength, int actualMaxValue) {
		// remaining needed Resources if actualMaxValue is chosen
		int remainingResources = activity.getNeededResources()
				- activity.getAllocatedResources() - actualMaxValue;
		this.remainingResources = remainingResources - minBlockLength
				* actualMaxValue;
		resource = ArraysUtil.createArray(activity.getLowerBound(),
				activity.getUpperBound());

		this.lowerBound = activity.getLowerBound();
		this.wcr = workContentResource;
		blockLength = ArraysUtil.createArray(wcr.getMinBlockLength(), Math.max(
				wcr.getLimit(), (this.remainingResources / lowerBound)));

		this.actualMaxValue = actualMaxValue;

	}

	public boolean execute() {
		if (remainingResources < 0) {
			return false;
		}
		// Is there a integer matching remainingResources, so
		// that remainingResources = integer*actualMaxValue
		boolean isIntegerExtendable = isInteger(((double) remainingResources)
				/ (double) actualMaxValue);
		if (isIntegerExtendable) {
			return true;
		}

		int v = 0;

		while (this.remainingResources > 0) {

			// the subset problem is the multiplication of blockLength and
			// resource
			// for every possibility
			int[] subsetProblem = ArraysUtil.multiplyArrays(resource,
					blockLength);
			if (SumOfSubset.subsetsum(subsetProblem, remainingResources)) {
				return true;
			}
			v++;
			this.remainingResources = this.remainingResources - v
					* actualMaxValue;
			this.blockLength = ArraysUtil.createArray(wcr.getMinBlockLength(),
					Math.max(wcr.getLimit(),
							(this.remainingResources / /*
														 * it is easier to use
														 * the lower bound here,
														 * the result is the
														 * same as fuendling
														 */lowerBound)));

		}
		return false;
	}

	private boolean isInteger(double d) {
		return d - ((int) d) == 0;
	}
}
